package dmxGroupControl.solvers;

import dmxGroupControl.Channel;
import dmxGroupControl.Fixture;
import dmxGroupControl.FixtureType;
import org.jdom2.Attribute;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by Kadmium on 16/10/2014.
 */
public class FakeStrobeSolver extends Solver
{
    private static List<String> solvableChannels = Arrays.asList(
        "Red", "Green", "Blue", "White", "MonoMaster");
    private static List<String> solvableAttributes = Arrays.asList("Chase");

    float value = 0.0f;
    Fixture fixture;
    int interval;
    int currentTimer;
    boolean strobeOn;
    boolean firstRun;

    List<Channel> applicableChannels;

    public FakeStrobeSolver(Fixture fixture, int interval)
    {
        this.fixture = fixture;
        this.interval = interval;
        this.currentTimer = interval;
        strobeOn = false;

        if(fixture.GetFixtureType() != FixtureType.LED)
        {
            throw new IllegalArgumentException("A fake strobe solver must ONLY be applied to an LED fixture");
        }

        firstRun = true;
    }

    public void SetInterval(int interval)
    {
        this.interval = interval;
    }

    public int GetInterval()
    {
        return interval;
    }

    private void FirstRun()
    {
        applicableChannels =
            fixture
                .GetChannels()
                .stream()
                .filter(channel -> Solver.SolvesForChannel(channel.GetName(), solvableChannels))
                .collect(Collectors.toList());
    }

    @Override
    public String GetType()
    {
        return "fakeStrobe";
    }

    @Override
    public void Set(String attributeName, float value)
    {
        switch(attributeName)
        {
            case "Strobe":
                this.value = value;
                break;
            default:
                return;
        }
    }

    @Override
    public boolean SolvesAttribute(String attribute)
    {
        return attribute.equals("Strobe");
    }

    @Override
    protected void SolveInternal()
    {
        if(firstRun)
        {
            firstRun = false;
            FirstRun();
        }
        if(value != 0.0f)
        {
            currentTimer--;
            if(currentTimer == 0)
            {
                currentTimer = interval;
                strobeOn = !strobeOn;
            }
            if(!strobeOn)
            {
                applicableChannels.stream().forEach(channel -> channel.SetValue(0.0f));
            }

        }
    }

    @Override
    public float GetAttribute(String name)
    {
        if(name.equals("Strobe"))
        {
            return value;
        }
        else
        {
            return 0.0f;
        }

    }

    public static boolean GetIsApplicableToFixture(Fixture fixture)
    {
        return fixture.GetFixtureType() == FixtureType.LED && Solver.GetIsApplicableToFixture(fixture, solvableChannels);
    }

    @Override
    public Collection<? extends Attribute> GetAttributes()
    {
        ArrayList<Attribute> attributes = new ArrayList<>();
        attributes.add(new Attribute("countdownFrames", interval + ""));
        return attributes;
    }
}
